//给你一个整数 n ，对于 0 <= i <= n 中的每个 i ，计算其二进制表示中 1 的个数 ，返回一个长度为 n + 1 的数组 ans 作为答案。 
//
//
// 
//
// 
// 
// 示例 1： 
// 
// 
//
// 
//输入：n = 2
//输出：[0,1,1]
//解释：
//0 --> 0
//1 --> 1
//2 --> 10
// 
//
// 示例 2： 
//
// 
//输入：n = 5
//输出：[0,1,1,2,1,2]
//解释：
//0 --> 0
//1 --> 1
//2 --> 10
//3 --> 11
//4 --> 100
//5 --> 101
// 
//
// 
//
// 提示： 
//
// 
// 0 <= n <= 10⁵ 
// 
//
// 
//
// 进阶： 
//
// 
// 很容易就能实现时间复杂度为 O(n log n) 的解决方案，你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗？ 
// 你能不使用任何内置函数解决此问题吗？（如，C++ 中的 __builtin_popcount ） 
// 
//
// Related Topics 位运算 动态规划 👍 1259 👎 0


package LeetCode.editor.cn;

/**
 * @author ldltd
 * @date 2023-10-07 16:32:57
 * @description 338.比特位计数
 */
public class CountingBits{
	 public static void main(String[] args) {
	 	 //测试代码
	 	 Solution solution = new CountingBits().new Solution();
		  //api  bitcount计算1个数
		 System.out.println(Integer.bitCount(3));
	 }
	 
//力扣代码
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
    public int[] countBits1(int n) {
		int [] res=new int[n+1];
		for (int i = 0; i <=n; i++) {
			int t=0;
			int x=i;
			while (x!=0){
				x-=lowbit(x);
				t++;
			}
			res[i]=t;
		}
		return res;
    }
	// x & -x == x & (~x + 1)
	//x-(x&(x-1))三种
	private   int lowbit(int x){
		return x&-x;  //返回最后一位1
	}

	public int[] countBits2(int n) {
		int[] bits = new int[n + 1];
		for (int i = 0; i <= n; i++) {
			bits[i] = countOnes(i);
			//bits[i]=Integer.bitCount(i);
		}
		return bits;
	}
	/*对于任意整数，令x=x&(x-1)
	* 将x的二进制表示最后一个1变为0直到变成0*/
	public int countOnes(int x) {
		int ones = 0;
		while (x > 0) {
			x &= (x - 1);
			ones++;
		}
		return ones;
	}

	/*如果当前是奇数，则1的个数比前一个偶数多1
	* 如果当前是偶数，则等于他折半的数的个数（进位）*/
	public int[] countBits3(int n) {
		int [] res=new int[n+1];
		for (int i = 1; i <=n ; i++) {
			if(i%2==1){
				res[i]=res[i-1]+1;
			}else {
				res[i]=res[i/2];
			}
		}
		return res;
	}
	/*最高有效位*/
	public int[] countBits4(int n) {
		int[] bits = new int[n + 1];
		int highBit = 0;
		for (int i = 1; i <= n; i++) {
			/*如果一个数是2的整数次幂，
			* (i & (i - 1)等于0，
			* 每次计算到整数幂时更新highbit
			* i比i-highbit的计数多1（最高位）*/
			if ((i & (i - 1)) == 0) {
				highBit = i;
			}
			bits[i] = bits[i - highBit] + 1;
		}
		return bits;
	}

	/*最低有效位
	* 如果是偶数，等于x/2,
	* 如果是偶数，等于x/2+1*/
	public int[] countBits5(int n) {
		int [] dp=new int[n+1];
		for (int i = 1; i <=n; i++) {
			dp[i]=dp[i>>1]+(i&1);
		}
		return dp;
	}
	/*最低设置位
	* i的计数等于将i的最后一位变成0的计数+1
	* 即dp[i]=dp[x&(x-1)]+1*/
	public int[] countBits(int n) {
		int [] dp=new int[n+1];
		for (int i = 1; i <=n; i++) {
			dp[i] = dp[i & (i - 1)] + 1;
		}
		return dp;
	}

}
//leetcode submit region end(Prohibit modification and deletion)

}
